package com.example.pathtracker.activity

import android.Manifest
import android.app.AlertDialog
import android.content.pm.PackageManager
import android.os.Bundle
import android.text.InputType
import android.util.Log
import android.widget.EditText
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import com.amap.api.location.AMapLocation
import com.amap.api.location.AMapLocationClient
import com.amap.api.location.AMapLocationClientOption
import com.amap.api.location.AMapLocationListener
import com.amap.api.maps.AMap
import com.amap.api.maps.CameraUpdateFactory
import com.amap.api.maps.model.BitmapDescriptorFactory
import com.amap.api.maps.model.LatLng
import com.amap.api.maps.model.Marker
import com.amap.api.maps.model.MarkerOptions
import com.amap.api.maps.model.MyLocationStyle
import com.bumptech.glide.Glide
import com.example.pathtracker.bean.MapPoint
import com.example.pathtracker.bean.PathData
import com.example.pathtracker.bean.PointTypeData
import com.example.pathtracker.databinding.ActivityPointMarkBinding
import com.example.pathtracker.net.RetrofitClient
import com.example.pathtracker.bean.UploadResponse
import com.example.pathtracker.utils.NetworkUtils
import com.example.pathtracker.utils.SPUtils
import com.google.gson.reflect.TypeToken
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import java.util.concurrent.Executors
import com.google.android.material.floatingactionbutton.FloatingActionButton
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.TextView
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.example.pathtracker.R

class PointMarkActivity : AppCompatActivity(), AMapLocationListener {
    private lateinit var binding: ActivityPointMarkBinding
    private lateinit var aMap: AMap
    private lateinit var locationClient: AMapLocationClient
    private var serverPointList = mutableListOf<MapPoint>() // 服务器点位列表
    private var localPointList = mutableListOf<MapPoint>() // 本地未提交点位列表
    private val markerMap = mutableMapOf<Marker, MapPoint>()
    private var pointTypeList: List<PointTypeData> = emptyList()
    private var currentPointType: PointTypeData? = null
    private var isFirstLocation = true // 标记是否为首次定位
    private var unsubmittedDialog: AlertDialog? = null // 保存对话框实例

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityPointMarkBinding.inflate(layoutInflater)
        setContentView(binding.root)
        supportActionBar?.title = "点位采集"
        supportActionBar?.setDisplayHomeAsUpEnabled(true) // 显示返回按钮
        binding.mapView.onCreate(savedInstanceState)
        aMap = binding.mapView.map
        setupMap()
        checkPermissions()
        initLocation()

        // 设置上传按钮点击事件
        binding.fabUpload.setOnClickListener {
            showUnsubmittedPointsDialog()
        }

        NetworkUtils.isNetworkAvailable(this).let {
            if (!it) {
                val type = object : TypeToken<List<PointTypeData>>() {}.type
                pointTypeList = SPUtils.getObject(this, "pointTypeList", type) ?: emptyList()
                val serverPointType = object : TypeToken<List<MapPoint>>() {}.type
                serverPointList =
                    SPUtils.getObject(this, "serverPointList", serverPointType) ?: mutableListOf()
                val localPointType = object : TypeToken<List<MapPoint>>() {}.type
                localPointList =
                    SPUtils.getObject(this, "localPointList", localPointType) ?: mutableListOf()
                Log.i(
                    "加载点位数据",
                    "serverPointList: ${serverPointList.size}, localPointList: ${localPointList.size}"
                )
                if (pointTypeList.isNotEmpty()) {
                    refreshMarkers()
                }
            } else {
                getPointTypeList()
            }
        }
    }

    private fun getPointTypeList() {
        Log.d("PointMarkActivity", "网络请求：开始获取点位类型")
        RetrofitClient.apiService.getAllPointType()
            .enqueue(object : Callback<UploadResponse<List<PointTypeData>>> {
                override fun onResponse(
                    call: Call<UploadResponse<List<PointTypeData>>>,
                    response: Response<UploadResponse<List<PointTypeData>>>
                ) {
                    if (response.isSuccessful) {
                        response.body()?.data?.let {
                            // 过滤掉无效数据
                            pointTypeList =
                                it.filter { type -> type != null && !type.typeName.isNullOrEmpty() }
                            Log.d("PointMarkActivity", "获取点位类型成功: ${pointTypeList.size} 个")
                            SPUtils.put(this@PointMarkActivity, "pointTypeList", pointTypeList)
                            getAllPoints() // 进入页面加载所有点位
                        }
                    } else {
                        Toast.makeText(
                            this@PointMarkActivity,
                            "获取点位类型失败",
                            Toast.LENGTH_SHORT
                        ).show()
                    }
                }

                override fun onFailure(
                    call: Call<UploadResponse<List<PointTypeData>>>,
                    t: Throwable
                ) {
                    Toast.makeText(
                        this@PointMarkActivity,
                        "获取点位类型失败: ${t.message}",
                        Toast.LENGTH_SHORT
                    ).show()
                }
            })
    }

    private fun getAllPoints() {
        RetrofitClient.apiService.getAllPoints()
            .enqueue(object : Callback<UploadResponse<List<MapPoint>>> {
                override fun onResponse(
                    call: Call<UploadResponse<List<MapPoint>>>,
                    response: Response<UploadResponse<List<MapPoint>>>
                ) {
                    if (response.isSuccessful) {
                        response.body()?.data?.let {
                            serverPointList.clear()
                            serverPointList.addAll(it)
                            // 加载本地未提交点位
                            val localPointType = object : TypeToken<List<MapPoint>>() {}.type
                            localPointList = SPUtils.getObject(
                                this@PointMarkActivity,
                                "localPointList",
                                localPointType
                            ) ?: mutableListOf()
                            refreshMarkers()
                            SPUtils.put(this@PointMarkActivity, "serverPointList", serverPointList)
                        }
                    } else {
                        Toast.makeText(this@PointMarkActivity, "加载点位失败", Toast.LENGTH_SHORT)
                            .show()
                    }
                }

                override fun onFailure(call: Call<UploadResponse<List<MapPoint>>>, t: Throwable) {
                    Toast.makeText(
                        this@PointMarkActivity,
                        "加载点位失败: ${t.message}",
                        Toast.LENGTH_SHORT
                    ).show()
                }
            })
    }

    private fun addPointToServer(point: MapPoint) {
        RetrofitClient.apiService.addPoint(point).enqueue(object : Callback<UploadResponse<Unit>> {
            override fun onResponse(
                call: Call<UploadResponse<Unit>>,
                response: Response<UploadResponse<Unit>>
            ) {
                if (response.isSuccessful) {
                    Toast.makeText(this@PointMarkActivity, "新增点位成功", Toast.LENGTH_SHORT)
                        .show()
                    getAllPoints()
                } else {
                    Toast.makeText(this@PointMarkActivity, "新增点位失败", Toast.LENGTH_SHORT)
                        .show()
                }
            }

            override fun onFailure(call: Call<UploadResponse<Unit>>, t: Throwable) {
                Toast.makeText(
                    this@PointMarkActivity,
                    "新增点位失败: ${t.message}",
                    Toast.LENGTH_SHORT
                ).show()
            }
        })
    }

    private fun deletePointFromServer(point: MapPoint) {
        // 如果id是空的  直接从本地集合中删除
        if (point.id == null) {
            localPointList.remove(point)
            SPUtils.put(this, "localPointList", localPointList)
            refreshMarkers()
            return
        }
        val id = point.id ?: return
        RetrofitClient.apiService.deletePoint(id).enqueue(object : Callback<UploadResponse<Unit>> {
            override fun onResponse(
                call: Call<UploadResponse<Unit>>,
                response: Response<UploadResponse<Unit>>
            ) {
                if (response.isSuccessful) {
                    Toast.makeText(this@PointMarkActivity, "删除点位成功", Toast.LENGTH_SHORT)
                        .show()
                    getAllPoints()
                } else {
                    Toast.makeText(this@PointMarkActivity, "删除点位失败", Toast.LENGTH_SHORT)
                        .show()
                }
            }

            override fun onFailure(call: Call<UploadResponse<Unit>>, t: Throwable) {
                Toast.makeText(
                    this@PointMarkActivity,
                    "删除点位失败: ${t.message}",
                    Toast.LENGTH_SHORT
                ).show()
            }
        })
    }

    private fun setupMap() {
        aMap.uiSettings.isZoomControlsEnabled = true
        aMap.uiSettings.isMyLocationButtonEnabled = false // 隐藏定位按钮

        // 只显示当前位置，不自动回弹
        val myLocationStyle = MyLocationStyle()
            .showMyLocation(true)
            .myLocationType(MyLocationStyle.LOCATION_TYPE_SHOW)

        aMap.apply {
            setMyLocationStyle(myLocationStyle)
            isMyLocationEnabled = true
        }

        aMap.setOnMapLongClickListener { latLng ->
            showAddPointDialog(latLng)
        }
        aMap.setOnMarkerClickListener { marker ->
            showMarkerOptionsDialog(marker)
            true
        }
    }

    private fun checkPermissions() {
        val permissions = arrayOf(
            Manifest.permission.ACCESS_FINE_LOCATION,
            Manifest.permission.ACCESS_COARSE_LOCATION
        )

        val permissionsToRequest = permissions.filter {
            ContextCompat.checkSelfPermission(this, it) != PackageManager.PERMISSION_GRANTED
        }.toTypedArray()

        if (permissionsToRequest.isNotEmpty()) {
            ActivityCompat.requestPermissions(this, permissionsToRequest, PERMISSION_REQUEST_CODE)
        }
    }

    private fun initLocation() {
        try {
            locationClient = AMapLocationClient(applicationContext)
            locationClient.setLocationListener(this)

            val locationOption = AMapLocationClientOption().apply {
                locationMode = AMapLocationClientOption.AMapLocationMode.Hight_Accuracy
                interval = 2000
                isNeedAddress = true
                isOnceLocation = true // 只定位一次
            }
            locationClient.setLocationOption(locationOption)
            locationClient.startLocation()
        } catch (e: Exception) {
            e.printStackTrace()
            Toast.makeText(this, "定位初始化失败", Toast.LENGTH_SHORT).show()
        }
    }

    override fun onLocationChanged(location: AMapLocation?) {
        location?.let {
            if (it.errorCode == 0) {
                val latLng = LatLng(it.latitude, it.longitude)
                if (isFirstLocation) {
                    aMap.animateCamera(CameraUpdateFactory.newLatLngZoom(latLng, 16f))
                    isFirstLocation = false
                    locationClient.stopLocation() // 只在首次定位后停止
                }
            } else {
                Toast.makeText(this, "定位失败: ${it.errorInfo}", Toast.LENGTH_SHORT).show()
            }
        }
    }

    private fun showAddPointDialog(latLng: LatLng) {
        if (pointTypeList.isEmpty()) {
            Toast.makeText(this, "正在加载点位类型，请稍后重试", Toast.LENGTH_SHORT).show()
            return
        }
        
        val dialogView = LayoutInflater.from(this).inflate(R.layout.dialog_add_point, null)
        val typeInput = dialogView.findViewById<EditText>(R.id.et_point_type)
        val nameInput = dialogView.findViewById<EditText>(R.id.et_point_name)
        val phoneInput = dialogView.findViewById<EditText>(R.id.et_phone)
        val btnCancel = dialogView.findViewById<Button>(R.id.btn_cancel)
        val btnAdd = dialogView.findViewById<Button>(R.id.btn_add)
        
        val typeNames = pointTypeList.map { it.typeName ?: "未知类型" }.toTypedArray()
        if (typeNames.any { it == null }) {
            Toast.makeText(this, "点位类型数据异常", Toast.LENGTH_SHORT).show()
            return
        }
        
        val dialog = AlertDialog.Builder(this)
            .setView(dialogView)
            .create()
        
        var selectedTypeIndex = 0
        typeInput.setText(typeNames[0])
        
        // 设置类型选择的点击事件
        typeInput.setOnClickListener {
            AlertDialog.Builder(this@PointMarkActivity)
                .setTitle("选择点位类型")
                .setSingleChoiceItems(typeNames, selectedTypeIndex) { typeDialog, which ->
                    selectedTypeIndex = which
                    typeInput.setText(typeNames[which])
                    typeDialog.dismiss()
                }
                .setNegativeButton("取消", null)
                .show()
        }
        
        btnCancel.setOnClickListener {
            dialog.dismiss()
        }
        
        btnAdd.setOnClickListener {
            val name = nameInput.text.toString().trim()
            val phone = phoneInput.text.toString().trim()
            if (name.isEmpty()) {
                Toast.makeText(this, "名称不能为空", Toast.LENGTH_SHORT).show()
                return@setOnClickListener
            }
            if (phone.isEmpty()) {
                Toast.makeText(this, "联系方式不能为空", Toast.LENGTH_SHORT).show()
                return@setOnClickListener
            }
            
            val type = pointTypeList[selectedTypeIndex]
            val point = MapPoint(
                lat = latLng.latitude,
                lng = latLng.longitude,
                pointName = name,
                typeId = type.id,
                typeName = type.typeName,
                phone = phone,
                id = null
            )
            
            if (NetworkUtils.isNetworkAvailable(this)) {
                addPointToServer(point)
            } else {
                Toast.makeText(this, "当前无网络连接，点位将在下次网络连接时同步", Toast.LENGTH_SHORT).show()
                localPointList.add(point)
                SPUtils.put(this, "localPointList", localPointList)
                refreshMarkers()
            }
            dialog.dismiss()
        }
        
        dialog.show()
    }

    private fun showMarkerOptionsDialog(marker: Marker) {
        val point = markerMap[marker] ?: return

        val message = """
            点位名称: ${point.pointName}
            点位类型: ${point.typeName}
            联系方式: ${point.phone}
            经纬度: ${point.lat}, ${point.lng}
        """.trimIndent()

        AlertDialog.Builder(this)
            .setTitle(point.pointName)
            .setMessage(message)
            .setPositiveButton("删除") { _, _ ->
                // 本地删除改为接口删除
                if (point.id != null) {
                    AlertDialog.Builder(this)
                        .setTitle("确认删除")
                        .setMessage("确定要删除该点位吗？")
                        .setPositiveButton("确定") { _, _ ->
                            deletePointFromServer(point)
                        }
                        .setNegativeButton("取消", null)
                        .show()
                } else {
                    AlertDialog.Builder(this)
                        .setTitle("确认删除")
                        .setMessage("确定要删除该未提交点位吗？")
                        .setPositiveButton("确定") { _, _ ->
                            localPointList.remove(point)
                            SPUtils.put(this, "localPointList", localPointList)
                            refreshMarkers()
                        }
                        .setNegativeButton("取消", null)
                        .show()
                }
            }
            .setNegativeButton("关闭", null)
            .show()
    }

    private fun refreshMarkers() {
        aMap.clear()
        markerMap.clear()
        val executor = Executors.newSingleThreadExecutor()

        // 先加载服务器点位
        for (point in serverPointList) {
            loadMarkerForPoint(point, executor, false)
        }

        // 再加载本地未提交点位
        for (point in localPointList) {
            loadMarkerForPoint(point, executor, true)
        }
    }

    private fun loadMarkerForPoint(
        point: MapPoint,
        executor: java.util.concurrent.Executor,
        isLocal: Boolean
    ) {
        // 匹配类型
        val type = pointTypeList.find { it.id == point.typeId }
        if (type != null) {
            val iconUrl = type.typeIcon
            executor.execute {
                try {
                    val future = Glide.with(this)
                        .asBitmap()
                        .load(iconUrl)
                        .submit(80, 80)
                    val bitmap = future.get()
                    runOnUiThread {
                        val markerOptions = MarkerOptions()
                            .position(LatLng(point.lat, point.lng))
                            .title(if (isLocal) "${point.pointName} (未提交)" else point.pointName)
                            .icon(BitmapDescriptorFactory.fromBitmap(bitmap))
                        val marker = aMap.addMarker(markerOptions)
                        markerMap[marker] = point
                    }
                } catch (e: Exception) {
                    e.printStackTrace()
                }
            }
        }
    }

    private fun showUnsubmittedPointsDialog() {
        // 先关闭现有对话框
        unsubmittedDialog?.dismiss()
        unsubmittedDialog = null
        
        val dialogView = LayoutInflater.from(this).inflate(R.layout.dialog_unsubmitted_points, null)
        val titleView = dialogView.findViewById<TextView>(R.id.tv_title)
        val recyclerView = dialogView.findViewById<RecyclerView>(R.id.rv_points)
        val btnClose = dialogView.findViewById<Button>(R.id.btn_close)
        val btnUploadAll = dialogView.findViewById<Button>(R.id.btn_upload_all)
        
        if (localPointList.isEmpty()) {
            titleView.text = "未提交点位"
            recyclerView.visibility = View.GONE
            btnUploadAll.visibility = View.GONE
            // 显示暂无数据的提示
            val emptyView = TextView(this).apply {
                text = "暂无未提交的点位数据"
                gravity = android.view.Gravity.CENTER
                setPadding(0, 40, 0, 40)
                setTextColor(android.graphics.Color.parseColor("#666666"))
            }
            (dialogView as android.widget.LinearLayout).addView(emptyView, 2)
        } else {
            titleView.text = "未提交点位 (${localPointList.size}个)"
            recyclerView.visibility = View.VISIBLE
            btnUploadAll.visibility = View.VISIBLE
            
            recyclerView.layoutManager = LinearLayoutManager(this)
            recyclerView.adapter = UnsubmittedPointsAdapter(localPointList) { point ->
                uploadPointFromDialog(point) {
                getAllPoints()
                    // 延迟刷新，确保数据更新完成
                    runOnUiThread {
                        refreshUnsubmittedDialog()
                    }
                }
            }
        }
        
        btnClose.setOnClickListener {
            unsubmittedDialog?.dismiss()
            unsubmittedDialog = null
        }
        
        btnUploadAll.setOnClickListener {
            uploadAllPoints()
        }
        
        unsubmittedDialog = AlertDialog.Builder(this)
            .setView(dialogView)
            .create()
        unsubmittedDialog?.show()
    }

    private fun uploadAllPoints() {
        if (localPointList.isEmpty()) {
            Toast.makeText(this, "没有可上传的点位", Toast.LENGTH_SHORT).show()
            return
        }
        
        val pointsToUpload = localPointList.toList() // 创建副本避免并发修改
        var uploadedCount = 0
        val totalCount = pointsToUpload.size
        
        pointsToUpload.forEach { point ->
            uploadPointFromDialog(point) {
                uploadedCount++
                if (uploadedCount == totalCount) {
                    Toast.makeText(this, "全部点位上传完成", Toast.LENGTH_SHORT).show()
                    getAllPoints()
                    // 强制刷新界面
                    runOnUiThread {
                        refreshUnsubmittedDialog()
                    }
                }
            }
        }
    }

    inner class UnsubmittedPointsAdapter(
        private val points: List<MapPoint>,
        private val onUploadClick: (MapPoint) -> Unit
    ) : RecyclerView.Adapter<UnsubmittedPointsAdapter.ViewHolder>() {

        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
            val view = LayoutInflater.from(parent.context)
                .inflate(R.layout.item_unsubmitted_point, parent, false)
            return ViewHolder(view)
        }

        override fun getItemCount(): Int = points.size

        override fun onBindViewHolder(holder: ViewHolder, position: Int) {
            holder.bind(points[position])
        }

        inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
            private val tvPointName: TextView = itemView.findViewById(R.id.tv_point_name)
            private val tvPointType: TextView = itemView.findViewById(R.id.tv_point_type)
            private val tvPhone: TextView = itemView.findViewById(R.id.tv_phone)
            private val tvCoordinates: TextView = itemView.findViewById(R.id.tv_coordinates)
            private val btnSubmit: Button = itemView.findViewById(R.id.btn_submit)

            fun bind(point: MapPoint) {
                tvPointName.text = point.pointName
                tvPointType.text = "类型: ${point.typeName}"
                tvPhone.text = "联系方式: ${point.phone}"
                tvCoordinates.text = "坐标: ${String.format("%.6f, %.6f", point.lat, point.lng)}"

                btnSubmit.setOnClickListener {
                    onUploadClick(point)
                }
            }
        }
    }

    private fun refreshUnsubmittedDialog() {
        // 重新创建对话框
        showUnsubmittedPointsDialog()
    }

    private fun uploadPointFromDialog(point: MapPoint, onSuccess: () -> Unit) {
        RetrofitClient.apiService.addPoint(point).enqueue(object : Callback<UploadResponse<Unit>> {
            override fun onResponse(
                call: Call<UploadResponse<Unit>>,
                response: Response<UploadResponse<Unit>>
            ) {
                if (response.isSuccessful && response.body()?.code == 200) {
                    Toast.makeText(this@PointMarkActivity, "上传成功", Toast.LENGTH_SHORT).show()
                    removePointFromLocal(point)
                    onSuccess()
                } else {
                    Toast.makeText(this@PointMarkActivity, "上传失败", Toast.LENGTH_SHORT).show()
                }
            }

            override fun onFailure(call: Call<UploadResponse<Unit>>, t: Throwable) {
                Toast.makeText(this@PointMarkActivity, "上传失败: ${t.message}", Toast.LENGTH_SHORT)
                    .show()
            }
        })
    }

    private fun removePointFromLocal(point: MapPoint) {
        localPointList.removeAll {
            it.pointName == point.pointName &&
                    it.lat == point.lat &&
                    it.lng == point.lng &&
                    it.typeId == point.typeId
        }
        SPUtils.put(this, "localPointList", localPointList)
        refreshMarkers()
    }

    override fun onResume() {
        super.onResume()
        binding.mapView.onResume()
    }

    override fun onPause() {
        super.onPause()
        binding.mapView.onPause()
    }

    override fun onDestroy() {
        super.onDestroy()
        binding.mapView.onDestroy()
        locationClient.onDestroy()
    }

    override fun onSaveInstanceState(outState: Bundle) {
        super.onSaveInstanceState(outState)
        binding.mapView.onSaveInstanceState(outState)
    }

    override fun onOptionsItemSelected(item: android.view.MenuItem): Boolean {
        if (item.itemId == android.R.id.home) {
            onBackPressedDispatcher.onBackPressed()
            return true
        }
        return super.onOptionsItemSelected(item)
    }

    companion object {
        private const val PERMISSION_REQUEST_CODE = 100
    }
} 